package com.framework.common.live;

import com.alibaba.druid.util.Utils;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.util.BeanUtil;
import com.framework.common.exception.RRException;
import com.framework.common.utils.QuickHelper;
import com.framework.common.utils.R;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.live.v20180801.LiveClient;
import com.tencentcloudapi.live.v20180801.models.*;
import netscape.javascript.JSObject;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.rmi.CORBA.Util;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.Map;

public class TencentLiveKit {

    protected static Logger logger = LoggerFactory.getLogger(TencentLiveKit.class);

    private static final char[] DIGITS_LOWER =
            {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};


    /**
     * 获取推流地址
     * 示例 ： rtmp://domain/AppName/StreamName?txSecret=Md5(key+StreamName+hex(time))&txTime=hex(time)
     * @param domain 推流URL
     * @param key 推流密钥
     * @param streamName 流名称
     * @param txTime 推流地址的有效时间时间戳
     * @return 返回推流 URL
     */
    public static String getPushUrl(String domain,String key, String streamName, long txTime) {
        return String.format("rtmp://%s/live/%s?%s", domain,streamName,getPushUrlQueryString(key,streamName,txTime));
    }

    /**
     * 更新腾讯回调模板
     * @param templateId
     * @param attrs
     * @param secretId
     * @param secretKey
     * @return
     */
    public static Boolean updateTencentLiveNotifyTemplate(Long templateId, Map<String,String> attrs,String secretId,String secretKey) {
        Boolean result = false;
        try {
            Credential cred = new Credential(secretId, secretKey);
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint("live.tencentcloudapi.com");
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);
            LiveClient client = new LiveClient(cred, "", clientProfile);

            ModifyLiveCallbackTemplateRequest req = new ModifyLiveCallbackTemplateRequest();
            req.setTemplateId(templateId);
            req.setTemplateName(attrs.get("TemplateName"));
            req.setCallbackKey(attrs.get("CallbackKey"));
            req.setDescription(attrs.get("Description"));
            req.setPornCensorshipNotifyUrl(attrs.get("PornCensorshipNotifyUrl"));
            req.setRecordNotifyUrl(attrs.get("RecordNotifyUrl"));
            req.setSnapshotNotifyUrl(attrs.get("SnapshotNotifyUrl"));
            req.setStreamBeginNotifyUrl(attrs.get("StreamBeginNotifyUrl"));
            req.setStreamEndNotifyUrl(attrs.get("StreamEndNotifyUrl"));
            req.setSnapshotNotifyUrl(attrs.get("SnapshotNotifyUrl"));

            logger.info(QuickHelper.object2json(req));

            ModifyLiveCallbackTemplateResponse resp = client.ModifyLiveCallbackTemplate(req);
            logger.info(ModifyLiveCallbackTemplateResponse.toJsonString(resp));

            result = true;
        } catch (TencentCloudSDKException e) {
            logger.error(e.getMessage());
            e.printStackTrace();
            throw new RRException(e.getMessage());
        }
        return result;
    }

    /**
     * 获取推流地址参数
     * 示例 ： rtmp://domain/AppName/StreamName?txSecret=Md5(key+StreamName+hex(time))&txTime=hex(time)
     * @param key 推流密钥
     * @param streamName 流名称
     * @param txTime 推流地址的有效时间时间戳
     * @return 返回一个URL QueryString ,该字符串并不是URL，需要绑定 domain 和 appname
     */
    public static String getPushUrlQueryString(String key, String streamName, long txTime) {
        String input = new StringBuilder().
                append(key).
                append(streamName).
                append(Long.toHexString(txTime).toUpperCase()).toString();
        String txSecret = null;
        try {
            MessageDigest messageDigest = MessageDigest.getInstance("MD5");
            txSecret  = byteArrayToHexString(
                    messageDigest.digest(input.getBytes("UTF-8")));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return txSecret == null ? "" :
                new StringBuilder().
                        append("txSecret=").
                        append(txSecret).
                        append("&").
                        append("txTime=").
                        append(Long.toHexString(txTime).toUpperCase()).
                        toString();
    }

    /**
     * 中断正在直播的直播流
     * @param streamName 流名称
     * @param domainName 推流域名
     * @param appName 应用名称,默认为 live
     * @param secretId secretId
     * @param secretKey secretKey
     * @return
     */
    public static Boolean dropLiveStream(String streamName,String domainName ,String appName ,String secretId,String secretKey) {
        Boolean result = false;
        try {
            logger.info("================== 腾讯云直播SDK 断播请求 ==================");
            Credential cred = new Credential(secretId, secretKey);
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint("live.tencentcloudapi.com");
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);
            LiveClient client = new LiveClient(cred, "", clientProfile);
            DropLiveStreamRequest req = new DropLiveStreamRequest();
            req.setStreamName(streamName);
            req.setDomainName(domainName);
            req.setAppName(appName);
            DropLiveStreamResponse resp = client.DropLiveStream(req);
            String str = DropLiveStreamResponse.toJsonString(resp);
            JSONObject res = QuickHelper.json2object(str,JSONObject.class);
            logger.info(QuickHelper.object2json(res));
            if(res.getString("RequestId").length()>0){
                result = true;
            }
        } catch (TencentCloudSDKException e) {
            logger.info("调用错误: %s".format(e.getMessage()));
        }
        return result;
    }


    /**
     * 禁用正在直播的直播流
     * @param streamName 流名称
     * @param domainName 推流域名
     * @param appName 应用名称,默认为 live
     * @param secretId secretId
     *
     *
     * @param secretKey secretKey
     * @return
     */
    public static Boolean forbidLiveStreamRequest(String streamName,String domainName ,String appName ,String secretId,String secretKey) {
        Boolean result = false;
        try {
            logger.info("================== 腾讯云直播SDK 禁播请求 ==================");
            Credential cred = new Credential(secretId, secretKey);
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint("live.tencentcloudapi.com");
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);
            LiveClient client = new LiveClient(cred, "", clientProfile);
            ForbidLiveStreamRequest req = new ForbidLiveStreamRequest();
            req.setStreamName(streamName);
            req.setDomainName(domainName);
            req.setAppName(appName);
            String pattern = "yyyy-MM-dd'T'HH:mm:ssZZ";
            req.setResumeTime(DateFormatUtils.format(new Date(), pattern));
            req.setReason(String.format("系统管理，禁用用户 %s 的直播", streamName));

            ForbidLiveStreamResponse resp = client.ForbidLiveStream(req);
            String str = DropLiveStreamResponse.toJsonString(resp);
            JSONObject res = QuickHelper.json2object(str, JSONObject.class);
            logger.info(QuickHelper.object2json(res));
            if (res.getString("RequestId").length() > 0) {
                result = true;
            }
        } catch (TencentCloudSDKException e) {
            logger.info("调用错误: %s".format(e.getMessage()));
        }
        return result;
    }

    /**
     * 恢复直播
     * @param streamName 流名称
     * @param domainName 推流域名
     * @param appName 应用名称,默认为 live
     * @param secretId secretId
     * @param secretKey secretKey
     * @return
     */
    public static Boolean resumeLiveStream(String streamName,String domainName ,String appName ,String secretId,String secretKey) {
        Boolean result = false;
        try {
            logger.info("================== 腾讯云直播SDK 恢复直播请求 ==================");
            Credential cred = new Credential(secretId, secretKey);
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint("live.tencentcloudapi.com");
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);
            LiveClient client = new LiveClient(cred, "", clientProfile);
            ResumeLiveStreamRequest req = new ResumeLiveStreamRequest();
            req.setStreamName(streamName);
            req.setDomainName(domainName);
            req.setAppName(appName);
            String pattern = "yyyy-MM-dd'T'HH:mm:ssZZ";

            ResumeLiveStreamResponse resp = client.ResumeLiveStream(req);
            String str = DropLiveStreamResponse.toJsonString(resp);
            JSONObject res = QuickHelper.json2object(str, JSONObject.class);
            logger.info(QuickHelper.object2json(res));
            if (res.getString("RequestId").length() > 0) {
                result = true;
            }
        } catch (TencentCloudSDKException e) {
            logger.info("调用错误: %s".format(e.getMessage()));
        }
        return result;
    }

    private static String byteArrayToHexString(byte[] data) {
        char[] out = new char[data.length << 1];
        for (int i = 0, j = 0; i < data.length; i++) {
            out[j++] = DIGITS_LOWER[(0xF0 & data[i]) >>> 4];
            out[j++] = DIGITS_LOWER[0x0F & data[i]];
        }
        return new String(out);
    }


}
